package model

import (
	"common/helper"
	"encoding/json"
	"errors"
	"fmt"
	g "github.com/doug-martin/goqu/v9"
	"github.com/go-redis/redis/v8"
)

type Priv struct {
	ID        string `db:"id" json:"id" redis:"id" cbor:"id"`                             //
	Name      string `db:"name" json:"name" redis:"name" cbor:"name"`                     //权限名字
	Module    string `db:"module" json:"module" redis:"module" cbor:"module"`             //模块
	Sortlevel string `db:"sortlevel" json:"sortlevel" redis:"sortlevel" cbor:"sortlevel"` //
	State     int    `db:"state" json:"state" redis:"state" cbor:"state"`                 //0:关闭1:开启
	Pid       int64  `db:"pid" json:"pid" redis:"pid" cbor:"pid"`                         //父级ID
}

func PrivList(gid, adminGid string) (string, error) {
	LoadPrivs()
	LoadGroups()
	if gid != "" {
		ok, err := groupSubCheck(gid, adminGid)
		if err != nil {
			return "[]", err
		}

		if !ok {
			return "[]", errors.New("权限不足")
		}
	} else {
		gid = adminGid
	}

	gKey := fmt.Sprintf("priv:list:GM%s", gid)
	// 运营总监分组
	//if gid == "2" || gid == "10" {
	//	gKey = fmt.Sprintf("%s:priv:PrivAll", meta.Prefix)
	//}
	cmd := meta.MerchantRedis.Get(ctx, gKey)

	val, err := cmd.Result()
	if err != nil && err != redis.Nil {
		return val, pushLog(err, helper.RedisErr)
	}

	return val, nil
}

func PrivCheck(uri, gid string) error {

	key := "priv:PrivMap"
	cmd := meta.MerchantRedis.HGet(ctx, key, uri)

	privId, err := cmd.Result()
	if err != nil {
		return pushLog(err, helper.RedisErr)
	}
	id := fmt.Sprintf("priv:GM%s", gid)
	hcmd := meta.MerchantRedis.HExists(ctx, id, privId)
	exists := hcmd.Val()
	if !exists {
		return errors.New("404")
	}

	return nil
}

func PrivCheckId(gid string, privId string) error {
	id := fmt.Sprintf("priv:GM%s", gid)
	hcmd := meta.MerchantRedis.HExists(ctx, id, privId)

	exists := hcmd.Val()
	if !exists {
		return errors.New("404")
	}
	return nil
}

/**
 * @Description: 刷新缓存
 * @Author: carl
 */
func LoadPrivs() error {

	records := privListRes{
		Status: 0,
	}
	query, _, _ := dialect.From("tbl_admin_priv").
		Select("pid", "state", "id", "name", "sortlevel", "module").Order(g.C("sortlevel").Asc()).ToSQL()
	query = "/* master */ " + query

	err := meta.MerchantDB.Select(&records.Data, query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	recs, err := json.Marshal(records)
	if err != nil {
		return errors.New("参数错误")
	}

	pipe1 := meta.MerchantRedis.Pipeline()
	defer pipe1.Close()

	privAllKey := "priv:PrivAll"
	pipe1.Unlink(ctx, privAllKey)
	pipe1.Set(ctx, privAllKey, string(recs), 0)
	pipe1.Persist(ctx, privAllKey)

	_, err = pipe1.Exec(ctx)
	if err != nil {
		return pushLog(err, helper.RedisErr)
	}

	pipe2 := meta.MerchantRedis.Pipeline()
	defer pipe2.Close()

	privMapKey := "priv:PrivMap"
	pipe2.Unlink(ctx, privMapKey)
	for _, val := range records.Data {
		pipe2.HSet(ctx, privMapKey, val.Module, val.ID)

	}
	pipe2.Persist(ctx, privMapKey)

	_, err = pipe2.Exec(ctx)
	if err != nil {
		return pushLog(err, helper.RedisErr)
	}

	return nil
}

/*
*
load whitelist
*/
//func LoadWhitelist() error {
//
//	var records []WhiteList
//	var listHt []string
//	var listFront []string
//
//	query, _, _ := dialect.From("tbl_whitelist").Select("ip", "ty").ToSQL()
//	query = "/* master */ " + query

//	err := meta.MerchantDB.Select(&records, query)
//	if err != nil {
//		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
//	}
//	for _, record := range records {
//		if record.Ty == "2" {
//			listFront = append(listFront, record.Ip)
//		} else {
//			listHt = append(listHt, record.Ip)
//		}
//	}
//	if len(listFront) > 0 {
//		pipe1 := meta.MerchantRedis.Pipeline()
//		defer pipe1.Close()
//
//		frontKey := fmt.Sprintf("%s:front:whitelist", meta.Prefix)
//		pipe1.Unlink(ctx, frontKey)
//		pipe1.SAdd(ctx, frontKey, listFront)
//
//		_, err = pipe1.Exec(ctx)
//		if err != nil {
//			return pushLog(err, helper.RedisErr)
//		}
//	}
//
//	if len(listHt) > 0 {
//		pipe2 := meta.MerchantRedis.Pipeline()
//		defer pipe2.Close()
//
//		htKey := fmt.Sprintf("%s:ht:whitelist", meta.Prefix)
//		pipe2.Unlink(ctx, htKey)
//		pipe2.SAdd(ctx, htKey, listHt)
//
//		_, err = pipe2.Exec(ctx)
//		if err != nil {
//			return pushLog(err, helper.RedisErr)
//		}
//	}
//
//	return nil
//}
